package com.inspur.edp.common.expr.visitor.field;

import com.inspur.edp.common.expr.ast.ASTContext;
import com.inspur.edp.common.expr.ast.CompileUnitParser;
import com.inspur.edp.common.expr.ast.CompileUnitVisitor;
import com.inspur.edp.common.expr.parser.ExpressAstParser;
import com.inspur.edp.common.expr.spi.FieldVisitor;
import com.inspur.edp.common.expr.visitor.VisitResult;
import com.inspur.edp.common.type.Field;
import com.inspur.edp.common.type.Type;
import com.inspur.edp.common.type.TypeRefer;
import com.inspur.edp.common.type.parser.TypeParser;
import com.inspur.edp.common.type.cache.TypeThreadCache;
import com.inspur.edp.common.type.utils.TypeUtil;

/**
 * @author lizhaorui
 * @date 2025/8/19
 * @description
 */
public class HashMapFieldVisitor implements FieldVisitor {

    public static final String KIND = "HashMap";

    @Override
    public String getKind() {
        return KIND;
    }

    @Override
    public VisitResult visitGetter(CompileUnitVisitor visitor,
                                   ASTContext context,
                                   CompileUnitParser.FieldAccessExprContext fieldAccessExprContext,
                                   CompileUnitParser.ExpressContext objectExpr,
                                   Field field) {
        TypeRefer objectType = ExpressAstParser.getOriginalType(objectExpr, context);
        TypeRefer fieldTypeRefer = TypeParser.getFieldType(objectType, field.getCode());
        String objectExprDsl = visitor.visitExpress(objectExpr).toString();
        Object tagValue = objectExpr.getTag(FieldVisitor.CLASS_CAST_TAG_KEY);
        if (tagValue != null) {
            objectExprDsl = "(" + objectExprDsl + ")";
        }
        String fieldCode = field.getCode();
        Type fieldType = TypeThreadCache.getType(fieldTypeRefer);
        String typeName = TypeUtil.getTypeCode(fieldType.getTypeOptCode());

        if (!typeName.contains(".")) {
            if (typeName.equalsIgnoreCase("double")) {
                typeName = "Double";
            } else if (typeName.equalsIgnoreCase("int")) {
                typeName = "Integer";
            } else if (typeName.equalsIgnoreCase("boolean")) {
                typeName = "Boolean";
            } else if (typeName.equalsIgnoreCase("long")) {
                typeName = "Long";
            }
        }
        String script = String.format("(%s)%s.get(\"%s\")", typeName, objectExprDsl, fieldCode);
        fieldAccessExprContext.putTag(FieldVisitor.CLASS_CAST_TAG_KEY, "1");
        VisitResult result = new VisitResult();
        result.setScript(script);
        result.addImport(fieldType.getTypeOptCode());
        return result;
    }

    @Override
    public VisitResult visitSetter(CompileUnitVisitor visitor, ASTContext context, CompileUnitParser.ExpressContext objectExpr, Field field, CompileUnitParser.ExpressContext valueExpr) {
        String objectExprDsl = visitor.visitExpress(objectExpr).toString();
        Object tagValue = objectExpr.getTag(FieldVisitor.CLASS_CAST_TAG_KEY);
        if (tagValue != null) {
            objectExprDsl = "(" + objectExprDsl + ")";
        }
        String valueExprDsl = visitor.visitExpress(valueExpr).toString();
        String fieldCode = field.getCode();
        String script = String.format("%s.put(\"%s\",%s)", objectExprDsl, fieldCode, valueExprDsl);
        VisitResult result = new VisitResult();
        result.setScript(script);
        return result;
    }
}